package com.javastudy.liuhouse.jdbc18;

import org.junit.Test;

import java.sql.*;

public class JdbcDmo1 {

    //JDBC连接的URL,不同的数据库有不同的格式
    private String JDBC_URL = "jdbc:mysql://localhost:3306/learnjdbc?useSSL=false&characterEncoding=utf8";
    private String JDBC_USER = "root";
    private String JDBC_PASSWORD = "root";

    @Test
    public void usejdbc(){
        //核心代码是  DriverManager 提供的静态方法getConnection()  DriverManager会自动扫描classpath
        //然后会找到所有的JDBC驱动，然后根据我们传入的URL自动挑选一个合适的驱动
        try(Connection connection = DriverManager.getConnection(this.JDBC_URL, this.JDBC_USER, this.JDBC_PASSWORD);) {
            //1.通过Connection 提供的 createStatement() 方法创建一个  Statement 对象，用于执行一个查询
            try(Statement statement = connection.createStatement()){
                String sql = "SELECT id , grade , name , gender FROM students WHERE gender = 1";
                //2.通过Statement 提供的 executeQuery() 方法 并传入 sql语句，并且查询并获得返回的结果集 , 使用ResultSet来引用和这个结果集
                try(ResultSet rs = statement.executeQuery(sql)){
                    //Statement 和 ResultSet 都是需要关闭的资源,因此嵌套使用  try(recource)确保及时关闭
                    //rs.next() 用于判断是否有下一行记录,入股哦呦,将自动把当前行移动到下一行(一开始获得 ResultSet时当前行不是第一行刚)
                    //ResultSet获取列的时候,索引是从1开始的 不是从0开始的   这是由设计者设计的  遵守即可
                    //必须根据  SELECT 对应的列来掉用户 getLong(1) , getString(2) 这些反复噶 ， 否则位置对应的数据类型不对的话， 就会报错
                    while (rs.next()){
                        long id = rs.getLong(1);//注意  这里的索引是从1开始的
                        long grade = rs.getLong(2);
                        String name = rs.getString(3);
                        int gender = rs.getInt(4);
                        System.out.println(id + " " + grade + " " + name + " " + gender);
                    }
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void usejdbc01(){
        try(Connection connection = DriverManager.getConnection(this.JDBC_URL , this.JDBC_USER , this.JDBC_PASSWORD)) {
           String sql = "SELECT id , grade , name , gender FROM students WHERE gender = ? AND grade = ?";
           //sql的预处理
            //使用PreparedStatement 和 Statement 稍有不同，必须首先调用 setObject() 设置每个占位符 ? 的值，最后获取的仍然是 ResultSet对象
            //另外需要注意的是从结果集读取数据的时候,使用String类型的列表比索引要读起来方便,而且不容易出错
           try(PreparedStatement statement = connection.prepareStatement(sql)){
                //给预处理语句  中预留的位置 进行值的填充
               statement.setObject(1 , "M");
               statement.setObject(2 , 3);
               //执行sql语句
               try(ResultSet resultSet = statement.executeQuery()){
                   //上面得到的是一个结果集
                   while (resultSet.next()){
                       long id = resultSet.getLong("id");
                       long grade = resultSet.getLong("grade");
                       String name = resultSet.getString("name");
                       String gender = resultSet.getString("gender");
                       System.out.println(id + " " + grade + " " + name + " " + gender);
                   }
               }
           }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }



    //增加数据
    @Test
    public void testInsert(){
        try (Connection connection = DriverManager.getConnection(this.JDBC_URL , this.JDBC_USER , this.JDBC_PASSWORD)){
            String sql = "INSERT INTO students (grade , name , gender,score) VALUES(?,?,?,?)";
            //在插入数据的时候需要获得主键id  那么在调用prepareStatement 的时候 必须传入第二个参数Statement.RETURN_GENERATED_KEYS
            //这是一个标志位  表示JDBC驱动必须返回自动插入的自动主键
            try(PreparedStatement statement = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS)){
                 //填入预定义的变量
                //传入的参数要和对应的字段的类型和数量保持一致
                statement.setObject(1, 1);
                statement.setObject(2  , "Bob");
                statement.setObject(3 , 1);
                statement.setObject(4  , 100);
                int n = statement.executeUpdate();
//                System.out.println(n);
                //第二个需要注意执行 executeUpdate() 方法的时候，必须调用getGeneratedKeys() 获取一个 ResultSet 对象
                //如果一次插入多条记录 ， 那么这个 ResultSet 就返回多条值
                try(ResultSet rs = statement.getGeneratedKeys()){
                    if(rs.next()){
                        long id = rs.getLong(1);
                        System.out.println(id);
                    }
                }
            }
        }catch (SQLException e){
            throw new RuntimeException(e);
        }
    }


    //更新操作
    @Test
    public void testUpdate(){
        try {
            try(Connection connection = DriverManager.getConnection(JDBC_URL,JDBC_USER,JDBC_PASSWORD)){
                String sql = "UPDATE students SET name = ? WHERE id = ?";
                try(PreparedStatement statement = connection.prepareStatement(sql)){
                    statement.setObject(1 , "Bob");
                    statement.setObject(2 , 2);
                    //executeUpdate() 返回数据库实际更新的函数  返回结果是正数  代表受影响的行数   如果返回的是0 代表没有任何的更新
                    int update = statement.executeUpdate();
                    System.out.println(update);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }



    //删除操作
    @Test
    public void testDelete(){
        try {
            try(Connection connection = DriverManager.getConnection(JDBC_URL,JDBC_USER,JDBC_PASSWORD)){
                String sql = "DELETE FROM students WHERE id = ?";
                try(PreparedStatement statement = connection.prepareStatement(sql)){
                    statement.setObject(1 , 3);
                    //executeUpdate() 返回数据库实际更新的函数  返回结果是正数  代表受影响的行数   如果返回的是0 代表没有任何的更新
                    int update = statement.executeUpdate();
                    System.out.println(update);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }



}
